//package client
//
//import (
//	"flag"
//	"fmt"
//	"os"
//	"path/filepath"
//	"tikrok/internal/version"
//)
//
//const usage1 string = `Usage: %s [OPTIONS] <local port or address>
//Options:
//`
//
//const usage2 string = `
//Examples:
//	tikrok 80
//	tikrok -subdomain=example 8080
//	tikrok -proto=tcp 22
//	tikrok -hostname="example.com" -httpauth="user:password" 10.0.0.1
//
//
//Advanced usage: tikrok [OPTIONS] <command> [command args] [...]
//Commands:
//	tikrok start [tunnel] [...]    Start tunnels by name from config file
//	tikrok start-all               Start all tunnels defined in config file
//	tikrok list                    List tunnel names from config file
//	tikrok help                    Print help
//	tikrok version                 Print tikrok version
//
//Examples:
//	tikrok start www api blog pubsub
//	tikrok -log=stdout -config=tikrok.yml start ssh
//	tikrok start-all
//	tikrok version
//
//`
//
//type Options struct {
//	config    string
//	logto     string
//	loglevel  string
//	authtoken string
//	httpauth  string
//	hostname  string
//	protocol  string
//	subdomain string
//	command   string
//	args      []string
//}
//
//func ParseArgs() (opts *Options, err error) {
//	flag.Usage = func() {
//		fmt.Fprintf(os.Stderr, usage1, os.Args[0])
//		flag.PrintDefaults()
//		fmt.Fprintf(os.Stderr, usage2)
//	}
//
//	config := flag.String(
//		"config",
//		"",
//		"Path to tikrok configuration file. (default: $HOME/.tikrok)")
//
//	logto := flag.String(
//		"log",
//		"none",
//		"Write log messages to this file. 'stdout' and 'none' have special meanings")
//
//	loglevel := flag.String(
//		"log-level",
//		"DEBUG",
//		"The level of messages to log. One of: DEBUG, INFO, WARNING, ERROR")
//
//	authtoken := flag.String(
//		"authtoken",
//		"",
//		"Authentication token for identifying an tikrok.com account")
//
//	httpauth := flag.String(
//		"httpauth",
//		"",
//		"username:password HTTP basic auth creds protecting the public tunnel endpoint")
//
//	subdomain := flag.String(
//		"subdomain",
//		"",
//		"Request a custom subdomain from the tikrok server. (HTTP only)")
//
//	hostname := flag.String(
//		"hostname",
//		"",
//		"Request a custom hostname from the tikrok server. (HTTP only) (requires CNAME of your DNS)")
//
//	protocol := flag.String(
//		"proto",
//		"http+https",
//		"The protocol of the traffic over the tunnel {'http', 'https', 'tcp'} (default: 'http+https')")
//
//	flag.Parse()
//
//	opts = &Options{
//		config:    *config,
//		logto:     *logto,
//		loglevel:  *loglevel,
//		httpauth:  *httpauth,
//		subdomain: *subdomain,
//		protocol:  *protocol,
//		authtoken: *authtoken,
//		hostname:  *hostname,
//		command:   flag.Arg(0),
//	}
//
//	switch opts.command {
//	case "list":
//		opts.args = flag.Args()[1:]
//	case "start":
//		opts.args = flag.Args()[1:]
//	case "start-all":
//		opts.args = flag.Args()[1:]
//	case "version":
//		fmt.Println(version.MajorMinor())
//		os.Exit(0)
//	case "help":
//		flag.Usage()
//		os.Exit(0)
//	case "":
//		err = fmt.Errorf("Error: Specify a local port to tunnel to, or " +
//			"an tikrok command.\n\nExample: To expose port 80, run " +
//			"'tikrok 80'")
//		return
//
//	default:
//		if len(flag.Args()) > 1 {
//			err = fmt.Errorf("You may only specify one port to tunnel to on the command line, got %d: %v",
//				len(flag.Args()),
//				flag.Args())
//			return
//		}
//
//		opts.command = "default"
//		opts.args = flag.Args()
//	}
//
//	return
//}

package client

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"tikrok/internal/version" // 保持原有包名不变
)

const usage1 string = `Usage: %s [OPTIONS] <local port or address>
Options:
`

const usage2 string = `
Examples:
	# 新增authtoken命令示例
	tikrok config authtoken <your_token>
	tikrok 80
	tikrok -subdomain=example 8080
	tikrok -proto=tcp 22
	tikrok -hostname="example.com" -httpauth="user:password" 10.0.0.1

Advanced usage: tikrok [OPTIONS] <command> [command args] [...]
Commands:
	tikrok start [tunnel] [...]    Start tunnels by name from config file
	tikrok start-all               Start all tunnels defined in config file
	tikrok list                    List tunnel names from config file
	tikrok help                    Print help
	tikrok version                 Print tikrok version

Examples:
	tikrok start www api blog pubsub
	tikrok -log=stdout -config=tikrok.yml start ssh
	tikrok start-all
	tikrok version

`

type Options struct {
	config    string
	logto     string
	loglevel  string
	authtoken string
	httpauth  string
	hostname  string
	protocol  string
	subdomain string
	command   string
	args      []string
}

func ParseArgs() (opts *Options, err error) {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, usage1, os.Args[0])
		flag.PrintDefaults()
		fmt.Fprintf(os.Stderr, usage2)
	}

	config := flag.String(
		"config",
		"",
		"Path to tikrok configuration file. (default: $HOME/.tikrok)")

	logto := flag.String(
		"log",
		"none",
		"Write log messages to this file. 'stdout' and 'none' have special meanings")

	loglevel := flag.String(
		"log-level",
		"DEBUG",
		"The level of messages to log. One of: DEBUG, INFO, WARNING, ERROR")

	authtoken := flag.String(
		"authtoken",
		"",
		"Authentication token for identifying an tikrok.com account")

	httpauth := flag.String(
		"httpauth",
		"",
		"username:password HTTP basic auth creds protecting the public tunnel endpoint")

	subdomain := flag.String(
		"subdomain",
		"",
		"Request a custom subdomain from the tikrok server. (HTTP only)")

	hostname := flag.String(
		"hostname",
		"",
		"Request a custom hostname from the tikrok server. (HTTP only) (requires CNAME of your DNS)")

	protocol := flag.String(
		"proto",
		"http+https",
		"The protocol of the traffic over the tunnel {'http', 'https', 'tcp'} (default: 'http+https')")

	flag.Parse()

	// 处理配置文件默认路径
	configPath := *config
	if configPath == "" {
		homeDir, err := os.UserHomeDir()
		if err != nil {
			return nil, fmt.Errorf("failed to get home directory: %v", err)
		}
		configPath = filepath.Join(homeDir, ".tikrok")
	}

	opts = &Options{
		config:    configPath, // 使用处理后的路径
		logto:     *logto,
		loglevel:  *loglevel,
		httpauth:  *httpauth,
		subdomain: *subdomain,
		protocol:  *protocol,
		authtoken: *authtoken,
		hostname:  *hostname,
		command:   flag.Arg(0),
	}

	// 协议校验
	validProtocols := map[string]bool{
		"http":       true,
		"https":      true,
		"tcp":        true,
		"http+https": true,
	}
	if !validProtocols[opts.protocol] {
		return nil, fmt.Errorf("invalid protocol '%s', must be one of http, https, tcp, or http+https", opts.protocol)
	}

	// 子命令处理
	switch opts.command {
	case "config":
		// 处理config authtoken命令
		if flag.Arg(0) == "config" {
			if flag.Arg(1) == "authtoken" {
				if flag.NArg() < 3 {
					err = fmt.Errorf("Missing authtoken argument\nUsage: tikrok config authtoken <YOUR_AUTHTOKEN>")
					return
				}
				if flag.NArg() > 3 {
					err = fmt.Errorf("Too many arguments for authtoken command")
					return
				}

				// 执行保存authtoken操作
				configPath := *config
				if configPath == "" {
					configPath = defaultPath()
				}

				if err = SaveAuthToken(configPath, flag.Arg(2)); err != nil {
					err = fmt.Errorf("Failed to save authtoken: %v", err)
					return
				}

				fmt.Printf("Authtoken saved to configuration file: %s\n", configPath)
				os.Exit(0)
			}
		}

	case "list":
		if len(flag.Args()) > 1 {
			return nil, fmt.Errorf("'list' command does not accept arguments")
		}
		opts.args = flag.Args()[1:]

	case "start":
		if len(flag.Args()) < 2 {
			return nil, fmt.Errorf("'start' command requires at least one tunnel name")
		}
		opts.args = flag.Args()[1:]

	case "start-all":
		if len(flag.Args()) > 1 {
			return nil, fmt.Errorf("'start-all' command does not accept arguments")
		}
		opts.args = flag.Args()[1:]

	case "version":
		fmt.Println(version.MajorMinor())
		os.Exit(0)

	case "help":
		flag.Usage()
		os.Exit(0)

	case "":
		err = fmt.Errorf("Error: Specify a local port or a valid command.\n\nExamples:\n\ttikrok 8080\n\ttikrok start ssh\n\ttikrok list")
		return

	default:
		if len(flag.Args()) > 1 {
			return nil, fmt.Errorf("you may only specify one port to tunnel to on the command line, got %d: %v",
				len(flag.Args()),
				flag.Args())
		}

		// 默认命令处理本地端口
		opts.command = "default"
		opts.args = flag.Args()

		// 基础端口校验
		if len(opts.args) == 1 {
			var port int
			if _, err := fmt.Sscanf(opts.args[0], "%d", &port); err != nil || port < 1 || port > 65535 {
				return nil, fmt.Errorf("invalid port number: %s", opts.args[0])
			}
		}
	}

	return opts, nil
}
